package models

import (
	"bigdevops/src/common"
	"fmt"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"strings"
)

// 采集任务 和机器的关系
// 1对多 机器只能属于1个采集任务
// 新建采集任务 就需要填入ip
// 主配置文件池
// job 对象 机器：ip+port
//
//	2 k8s 的服务发现：集群外部采集
//
// D:\nyy_work\go_path\src\github.com\prometheus\prometheus\model\rulefmt\rulefmt.go
type MonitorAlertRule struct {
	Model        // 不用每次写ID 和 createAt了
	Name  string `json:"name" validate:"required,min=1,max=50" gorm:"uniqueIndex;type:varchar(100);comment:告警规则名称，支持使用通配符*进行模糊搜索" `

	// D:\nyy_work\go_path\src\github.com\prometheus\prometheus\config\config.go
	// 下面是global段
	UserID uint

	// 公共的
	PoolId      uint `json:"poolId" gorm:"comment:关联哪个Prometheus实例的"`
	SendGroupId uint `json:"sendGroupId"`
	TreeNodeId  uint `json:"treeNodeId" gorm:"comment:绑定到哪个节点的"`
	Enable      int  `json:"enable" gorm:"comment:是否被开启 1正常 2关闭"` //用户是否被冻结 1正常 2冻结

	Expr        string      `json:"expr" gorm:"type:text;comment: 规则ql"`
	Severity    string      `json:"severity" gorm:"comment:告警级别 critical warning "`
	GrafanaLink string      `json:"grafanaLink" gorm:"type:text;comment: 大盘连接图"`
	ForTime     string      `json:"forTime" gorm:"comment: 持续时间 到这个时间才触发"`
	Labels      StringArray `json:"labels" gorm:"comment: 标签组 key=v ,scrape_ip=1.1.1.1 "`
	Annotations StringArray `json:"annotations" gorm:"comment: 注解 key=v ,scrape_ip=1.1.1.1 "`

	NodePath       string `json:"nodePath" gorm:"-"` // a.b.c.d
	TreeNodeIdInts []int  `json:"treeNodeIdInts" gorm:"-"`
	Key            string `json:"key" gorm:"-"` //给前端表格

	PoolName       string `json:"poolName" gorm:"-"`      //给前端表格
	SendGroupName  string `json:"sendGroupName" gorm:"-"` //给前端表格
	CreateUserName string `json:"createUserName" gorm:"-"`

	// \n join后的string
	LabelsFront      string            `json:"labelsFront" gorm:"-"`
	AnnotationsFront string            `json:"annotationsFront" gorm:"-"`
	LabelsM          map[string]string `json:"labelsM" gorm:"-"`
	AnnotationsM     map[string]string `json:"annotationsM" gorm:"-"`
}

func (obj *MonitorAlertRule) Create() error {
	return Db.Create(obj).Error

}
func (obj *MonitorAlertRule) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func (obj *MonitorAlertRule) CreateOne() error {
	return Db.Create(obj).Error

}

func (obj *MonitorAlertRule) UpdateOne() error {
	return Db.Debug().Where("id = ?", obj.ID).Updates(obj).Error

}

//func (obj *MonitorAlertRule) ValidateRelabelConfigsYamlString() error {
//	var relabelConfigsObj []*relabel.Config
//	return yaml.Unmarshal([]byte(obj.RelabelConfigsYamlString), &relabelConfigsObj)
//
//}

func (obj *MonitorAlertRule) GenMapFromKvs(kvs []string) map[string]string {

	labelsM := map[string]string{}
	for _, i := range kvs {
		kvs := strings.Split(i, "=")
		if len(kvs) != 2 {
			continue
		}
		k := kvs[0]
		v := kvs[1]
		labelsM[k] = v
	}
	return labelsM

}

// 0值替换 前转后
func (obj *MonitorAlertRule) FillDefaultData() {
	if obj.ForTime == "" {
		obj.ForTime = "1m"
	}

	obj.Labels = common.GenStringArrayByChangeLine(obj.LabelsFront)
	obj.Annotations = common.GenStringArrayByChangeLine(obj.AnnotationsFront)
	// 必须要添加 value annotation description_value
	//found := false
	//for _, ann := range obj.Annotations {
	//	if strings.HasPrefix(ann, common.MONITOR_RULE_ANNO_VALUE) {
	//		found = true
	//		break
	//	}
	//}
	//if !found {
	//	obj.Annotations = append(obj.Annotations, fmt.Sprintf("%s=%s",
	//		common.MONITOR_RULE_ANNO_VALUE,
	//		"{{ $value }}"))
	//}

}

func (obj *MonitorAlertRule) FillFrontAllData() {
	dbUser, _ := GetUserById(int(obj.UserID))
	if dbUser != nil {
		obj.CreateUserName = dbUser.Username
	}

	//dbPoll, _ := GetMonitorScrapePoolById(int(obj.PoolId))
	//if dbPoll != nil {
	//	obj.PoolName = dbPoll.Name
	//}

	prom, _ := GetMonitorScrapePoolById(int(obj.PoolId))
	if prom != nil {
		obj.PoolName = prom.Name
	}
	sendGroup, _ := GetMonitorSendGroupById(int(obj.SendGroupId))
	if sendGroup != nil {
		obj.SendGroupName = sendGroup.Name
	}

	node, _ := GetStreeNodeById(int(obj.TreeNodeId))
	if node != nil {
		node.FillFrontAllData()
		obj.NodePath = node.NodePath
	}

	obj.LabelsFront = strings.Join(obj.Labels, "\n")
	obj.AnnotationsFront = strings.Join(obj.Annotations, "\n")
	obj.Key = fmt.Sprintf("%d", obj.ID)
	obj.LabelsM = obj.GenMapFromKvs(obj.Labels)
	// 绑定发送组标签
	obj.LabelsM[common.MONITOR_ALERT_MATCH_KEY] = fmt.Sprintf("%d", obj.SendGroupId)
	obj.LabelsM[common.MONITOR_ALERT_RULE_KEY] = fmt.Sprintf("%d", obj.ID)
	obj.LabelsM[common.MONITOR_ALERT_SEVERITY_KEY] = obj.Severity
	obj.LabelsM[common.MONITOR_ALERT_BIND_NODE_KEY] = obj.NodePath
	obj.AnnotationsM = obj.GenMapFromKvs(obj.Annotations)
	// 必须要添加 value annotation description_value
	obj.AnnotationsM[common.MONITOR_RULE_ANNO_VALUE] = "{{ $value }}"

	//ids := []int{}
	//for _, id := range obj.TreeNodeIds {
	//	idInt, _ := strconv.Atoi(id)
	//	ids = append(ids, idInt)
	//}
	//obj.TreeNodeIdInts = ids

}
func GetMonitorAlertRuleAll() (objs []*MonitorAlertRule, err error) {
	err = Db.Find(&objs).Error
	return
}

func GetMonitorAlertRuleCount() int {
	var count int64
	Db.Table("form_designs").Count(&count)
	return int(count)
}

func GetMonitorAlertRuleByLevel(level int) (objs []*MonitorAlertRule, err error) {
	err = Db.Where("level = ?", level).Preload("OpsAdmins").Find(&objs).Error
	return
}

// select * from ecs where
func GetMonitorAlertRuleByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*MonitorAlertRule, err error) {
	err = Db.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

// 查询这个节点池管理的采集Job
func GetMonitorAlertRuleByPoolId(poolId uint) (objs []*MonitorAlertRule, err error) {

	err = Db.Where("enable=1 and pool_id = ?", poolId).Find(&objs).Error
	return

}

func GetMonitorAlertRuleBySendGroupId(sendGroupId uint) (objs []*MonitorAlertRule, err error) {

	err = Db.Where("send_group_id = ?", sendGroupId).Find(&objs).Error
	return

}

func GetMonitorAlertRuleById(id int) (*MonitorAlertRule, error) {

	var dbObj MonitorAlertRule
	err := Db.Where("id = ?", id).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("MonitorAlertRule不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
